package edu.hawaii.duedates;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import argparser.ArgParser;
import argparser.IntHolder;
import argparser.StringHolder;
import com.meterware.httpunit.WebConversation;
import com.meterware.httpunit.WebLink;
import com.meterware.httpunit.WebResponse;
import com.meterware.httpunit.WebTable;

/**
 * Due Dates main class for logging in to various libraries and retrieving due date information. The
 * class uses the LibraryVault object and HttpUnit classes to login and scan a given web page for
 * due date information.
 * 
 * @author Tyler Wolff and Scheller Sanchez
 */
public class DueDates {

  /* URL's for every possible library system */
  private static final String hslUrl = "http://www.librarieshawaii.org/";
  private static final String uhUrl = "http://uhmanoa.lib.hawaii.edu/cgi-bin/Pwebrecon."
      + "cgi?DB=local&PAGE=pbLogon";

/////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  
  /**
   * Utilizes a users information to login to a given library system and gather data about the users
   * current check out books.
   * 
   * @param hawaiiStateLib LibraryVault object for Hawaii State Library.
   * @param param1 First user parameter for logging in.
   * @param param2 Second user parameter for logging in.
   * @return A list of ItemDue Objects
   */
  private static List<ItemDue> getHslInfo (LibraryVault hawaiiStateLib, int param1,int param2) {
    try {

      WebConversation conversation = hawaiiStateLib.login(Integer.toString(param1), 
          Integer.toString(param2));
      WebResponse response = conversation.getCurrentPage();
      WebLink link = response.getLinkWith("Items Out");
      link.click();
      response = conversation.getCurrentPage();
      boolean noBooksOut = response.getText().contains("Checked Out: 0");
      String whiteSpace = "                                                  "; 
      List<ItemDue> itemsDue = new ArrayList<ItemDue>();
      
      if (!noBooksOut) {
        WebTable table = response.getTableStartingWith("Title");
        
        for (int i = 1; i < table.getRowCount(); i++) {
          String [] tempTitle = table.getCellAsText(i, 0).split("\n", 2);
          String Title = tempTitle[0].substring(2);
          Title = Title.concat(tempTitle[1]).concat(whiteSpace);
          ItemDue tempItem = new ItemDue("Hawaii State Library", Title, "n/a", 
              table.getCellAsText(i, 2));
          itemsDue.add(tempItem);
        }
      }
      
      return itemsDue;
    }
    catch (Exception e) {
      System.out.println("Error getting Hawaii State Library info");
      return null;
    }
    
  }

/////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  
  /**
   * Given valid login information for the UH Library site, provides info 
   * about a user's borrowed library books. 
   * 
   * @param libSystem The systems libraryVault object.
   * @param id The UH user ID.
   * @param lastName The UH user's last name.
   * @return A List of ItemDue objects.
   * @throws LoginException If problems occur Logging in.
   */
  public static List<ItemDue> getUhInfo(LibraryVault libSystem, String id, String lastName)
      throws LoginException {

    try {
      WebConversation conversation = libSystem.login(id, lastName);
      WebResponse response = conversation.getCurrentPage();
      WebTable tableOut = null;
      WebTable[] tables = response.getTables();
      String whiteSpace = "                                                  ";          
        
      for (WebTable table : tables) {
        if (table.getText().contains("Checked Out")) {
          tableOut = table;
        }
      }
      
      List<ItemDue> itemsDue = new ArrayList<ItemDue>();

      if (tableOut != null) {

        // Checks for table with renew option (No patron blocks)
        if (tableOut.getText().contains("Renew")) {
          for (int i = 1; i < tableOut.getRowCount(); i++) {
            ItemDue tempItem = new ItemDue("UH Manoa", 
                tableOut.getCellAsText(i, 1).concat(whiteSpace), tableOut
                .getCellAsText(i, 2), tableOut.getCellAsText(i, 3).substring(17));
            itemsDue.add(tempItem);
          }
        }
        // Checks for table without renew option (With patron blocks)
        else {
          for (int i = 1; i < tableOut.getRowCount(); i++) {
            ItemDue tempItem = new ItemDue("UH Manoa", 
                tableOut.getCellAsText(i, 0).concat(whiteSpace), tableOut
                .getCellAsText(i, 1), tableOut.getCellAsText(i, 2).substring(17));
            itemsDue.add(tempItem);
          }
        }

      } // end if

      return itemsDue;

    } // end try
    catch (Exception e) {
      throw new LoginException(e);
    }
  }

/////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  /**
   * Utilizes ArgParser to specify and verify the command line arguments. Upon
   * parsing, method takes action on whatever is specified by user. 
   * EXAMPLE -uhm 12345678 LastName -- will create UH Manoa LibraryVault object
   * and gather information about all borrowed books in system.
   * 
   * @param params The command line arguments.
   */
  public void parseArgsAndAct(String[] params) {

    // Variables to hold command line arguments
    String[] uhCommandInfo = new String[2];
    int[] hslParam = { -1, -1 };
    StringHolder sort = new StringHolder();
    IntHolder within = new IntHolder();
    String sortParameter;

    // Will hold total list of ItemDue Objects
    List<ItemDue> allItemsDue = new ArrayList<ItemDue>();
    List<ItemDue> itemsDueUH = new ArrayList<ItemDue>();
    List<ItemDue> itemsDueHsl = new ArrayList<ItemDue>();

    // Creating parser with Option values
    ArgParser parser = new ArgParser("java argparser.DueDates");
    parser.addOption("-uhm %sX2 #id and last name for UH Manoa Library", uhCommandInfo);
    parser.addOption("-hsl %dX2 #id and last 4 digits of telephone number for hawaii "
        + "state library system", hslParam);
    parser.addOption("-sort %s {library, duedate} #name of parameter to sort", sort);
    parser.addOption("-within %d {[0, 365]} #integer representing days to sort within", within);

    // Matching parameters to Options
    parser.matchAllArgs(params);

    // If -uhm parameters were given
    if (uhCommandInfo[0] != null && uhCommandInfo[1] != null) {

      LibraryVault uhManoa = new LibraryVault(uhUrl, "logonpage", "BC", "LN");
      System.out.println("Getting Data from UH Manoa Library...");
      try {
        itemsDueUH = getUhInfo(uhManoa, uhCommandInfo[0], uhCommandInfo[1]);
        
        if (itemsDueUH.isEmpty()) {
          System.out.println("No books out.");
        }
      }
      catch (LoginException e) {
        e.printStackTrace();
      }

    } // ends uh Manoa if

    // Checks for Hawaii State Library parameters
    if (hslParam[0] != -1 && hslParam[1] != -1) {
      System.out.println("Getting Data from the Hawaii State Library...");
      LibraryVault hawaiiStateLib = new LibraryVault(hslUrl, null, "sec1", "sec2");
      
      itemsDueHsl = getHslInfo(hawaiiStateLib, hslParam[0], hslParam[1]);
      
      if (itemsDueHsl.isEmpty()) {
        System.out.println("No books out.");
      }
    }

    if (!itemsDueUH.isEmpty()) {
      allItemsDue.addAll(itemsDueUH);
    }
    if (!itemsDueHsl.isEmpty()) {
      allItemsDue.addAll(itemsDueHsl);
    }
    
    // Check values of sort
    if (sort.value == null) {
      sortParameter = "library";
    } 
    else {
      sortParameter = sort.value;
    }
    
    printDueItems(allItemsDue, sortParameter, within.value);
  }

/////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  
  /**
   * Prints a given list of Items that are due.
   * 
   * @param itemsDue A list of ItemDue objects.
   * @param sort Specifies how to sort list, if specified
   * @param within Specifies the amount of time within due date to sort 
   */
  public static void printDueItems(List<ItemDue> itemsDue, String sort, int within) {

    String format = "|%1$-23s|%2$-50s|%3$-20s|%4$-10s|\n"; // format for output
    System.out.format(format, "LIBRARY", "ITEM DESCRIPTION", "ITEM TYPE", "DUE DATE");

    if ("library".equals(sort)) {
      Collections.sort(itemsDue, ItemDue.libraryComparator);
    }
    else if ("duedate".equals(sort)) {
      Collections.sort(itemsDue, ItemDue.dueDateComparator);  
    }
    
    for (ItemDue item : itemsDue) {
      System.out.format(format, item.itemLib, item.itemName.substring(0, 47) + "...",
          item.itemType, item.itemDueDate);
    }
    
  }

/////////////////////////////////////////////\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
  
  /**
   * Utilizes a users information to login to a given library system and gather data about the users
   * current check out books.
   * 
   * @param params The command line arguments.
   * @throws Exception If problems occur accessing the library sites.
   */
  public static void main(String[] params) throws Exception {

    DueDates dueDate = new DueDates();
    dueDate.parseArgsAndAct(params);

  }
}
